<template>
  <div class="vue-article">
    <div class="article-header">
      <h1>Vue.js 深度解析：现代前端开发的艺术与科学</h1>
      <div class="meta-info">
        <span class="author">作者：前端架构师</span>
        <span class="date">2024年1月15日</span>
        <span class="category">分类：前端框架</span>
      </div>
    </div>

    <div class="article-content">
      <section class="chapter">
        <h2>引言：为什么选择 Vue.js？</h2>
        <p>
          在当今快速发展的前端开发领域，Vue.js
          以其优雅的设计、渐进式的理念和出色的开发者体验，赢得了全球开发者的青睐。从初创公司到大型企业，Vue.js
          都在证明其作为现代 Web 应用开发首选框架的价值。
        </p>
        <p>
          Vue
          的成功并非偶然。其核心设计哲学——"渐进式框架"，意味着开发者可以根据项目需求，逐步采用
          Vue 的功能。无论是简单的交互增强，还是复杂的单页应用，Vue
          都能提供恰到好处的解决方案。
        </p>
      </section>

      <section class="chapter">
        <h2>Vue 3 的革命性变化</h2>

        <h3>组合式 API：重新思考组件逻辑</h3>
        <p>
          Vue 3 引入的组合式 API 是对传统选项式 API
          的重大革新。它解决了在复杂组件中逻辑关注点分散的问题，提供了更好的逻辑组织和复用能力。
        </p>

        <pre><code>// 组合式 API 示例
import { ref, computed, onMounted } from 'vue'

export default {
  setup() {
    // 响应式状态
    const count = ref(0)
    const todos = ref([])
    
    // 计算属性
    const completedTodos = computed(() => {
      return todos.value.filter(todo => todo.completed)
    })
    
    // 方法
    const increment = () => count.value++
    const addTodo = (text) => {
      todos.value.push({
        id: Date.now(),
        text,
        completed: false
      })
    }
    
    // 生命周期
    onMounted(async () => {
      // 组件挂载后的逻辑
      const response = await fetch('/api/todos')
      todos.value = await response.json()
    })
    
    return {
      count,
      todos,
      completedTodos,
      increment,
      addTodo
    }
  }
}</code></pre>

        <h3>响应式系统的重构</h3>
        <p>
          Vue 3 使用 Proxy 重写了响应式系统，解决了 Vue 2 中
          Object.defineProperty
          的限制。新的响应式系统提供了更好的性能和对新数据结构的支持。
        </p>

        <pre><code>// 响应式 API 深度使用
import { reactive, watchEffect, watch, toRefs } from 'vue'

const state = reactive({
  user: {
    name: 'Alice',
    profile: {
      age: 25,
      preferences: {
        theme: 'dark'
      }
    }
  },
  settings: {
    language: 'zh-CN'
  }
})

// 深度响应式
watchEffect(() => {
  console.log('用户主题变更:', state.user.profile.preferences.theme)
})

// 精确控制监听
watch(
  () => state.user.name,
  (newName, oldName) => {
    console.log(`用户名从 ${oldName} 变更为 ${newName}`)
  }
)

// 解构保持响应式
const { user, settings } = toRefs(state)</code></pre>
      </section>

      <section class="chapter">
        <h2>组件设计模式与最佳实践</h2>

        <h3>单一职责原则</h3>
        <p>
          每个组件应该只负责一个特定的功能或业务逻辑。这提高了组件的可维护性和可测试性。
        </p>

        <pre><code>// 不好的做法：组件承担过多职责
&lt;template&gt;
  &lt;div&gt;
    &lt;user-profile :user="user" /&gt;
    &lt;order-list :orders="orders" /&gt;
    &lt;payment-method :methods="paymentMethods" /&gt;
    &lt;recommendation :products="recommendations" /&gt;
  &lt;/div&gt;
&lt;/template&gt;

// 好的做法：拆分为专注的组件
&lt;template&gt;
  &lt;div class="user-dashboard"&gt;
    &lt;user-info-section :user="user" /&gt;
    &lt;recent-activity-section :activities="activities" /&gt;
    &lt;preferences-section :preferences="preferences" /&gt;
  &lt;/div&gt;
&lt;/template&gt;</code></pre>

        <h3>Props 设计原则</h3>
        <p>
          合理的 Props 设计是组件可复用的关键。应该明确 Props
          的类型、默认值和验证规则。
        </p>

        <pre><code>import { defineComponent, PropType } from 'vue'

interface User {
  id: number
  name: string
  email: string
  avatar?: string
}

export default defineComponent({
  name: 'UserCard',
  props: {
    // 必需的用户数据
    user: {
      type: Object as PropType&lt;User&gt;,
      required: true,
      validator: (user: User) => {
        return user.id && user.name && user.email
      }
    },
    // 可选的尺寸配置
    size: {
      type: String as () => 'small' | 'medium' | 'large',
      default: 'medium',
      validator: (value: string) => {
        return ['small', 'medium', 'large'].includes(value)
      }
    },
    // 布尔值标志
    clickable: {
      type: Boolean,
      default: false
    },
    // 复杂的配置对象
    theme: {
      type: Object as PropType&lt;{
        primaryColor: string
        backgroundColor: string
        textColor: string
      }&gt;,
      default: () => ({
        primaryColor: '#409EFF',
        backgroundColor: '#FFFFFF',
        textColor: '#303133'
      })
    }
  },
  emits: {
    // 明确声明事件
    'user-click': (user: User) => !!user,
    'follow': null
  },
  setup(props, { emit }) {
    const handleClick = () => {
      if (props.clickable) {
        emit('user-click', props.user)
      }
    }
    
    const handleFollow = () => {
      emit('follow')
    }
    
    return {
      handleClick,
      handleFollow
    }
  }
})</code></pre>
      </section>

      <section class="chapter">
        <h2>高级模式与技巧</h2>

        <h3>渲染函数与 JSX</h3>
        <p>
          虽然模板在大多数情况下是首选，但在需要更强大编程能力的场景下，渲染函数和
          JSX 提供了更大的灵活性。
        </p>

        <pre><code>import { defineComponent, h, resolveComponent } from 'vue'

export default defineComponent({
  name: 'DynamicForm',
  props: {
    fields: {
      type: Array as () => Array&lt;{
        type: 'input' | 'select' | 'textarea'
        name: string
        label: string
        options?: Array&lt;{ label: string; value: any }&gt;
      }&gt;,
      required: true
    }
  },
  setup(props) {
    const formData = ref({})
    
    const renderField = (field) => {
      const commonProps = {
        modelValue: formData.value[field.name],
        'onUpdate:modelValue': (value) => {
          formData.value[field.name] = value
        },
        placeholder: `请输入${field.label}`
      }
      
      switch (field.type) {
        case 'input':
          return h(resolveComponent('ElInput'), commonProps)
        case 'select':
          return h(resolveComponent('ElSelect'), commonProps, {
            default: () => field.options?.map(option => 
              h(resolveComponent('ElOption'), {
                label: option.label,
                value: option.value
              })
            )
          })
        case 'textarea':
          return h(resolveComponent('ElInput'), {
            ...commonProps,
            type: 'textarea',
            rows: 4
          })
        default:
          return null
      }
    }
    
    return () => h('div', { class: 'dynamic-form' }, 
      props.fields.map(field => 
        h('div', { class: 'form-field' }, [
          h('label', { class: 'field-label' }, field.label),
          renderField(field)
        ])
      )
    )
  }
})</code></pre>

        <h3>自定义指令的强大能力</h3>
        <p>
          自定义指令允许开发者直接对 DOM 元素进行底层操作，为 Vue
          应用添加特殊的行为。
        </p>

        <pre><code>// 权限指令
const permission = {
  mounted(el, binding) {
    const { value } = binding
    const userPermissions = getUserPermissions()
    
    if (!hasPermission(userPermissions, value)) {
      el.parentNode?.removeChild(el)
    }
  }
}

// 图片懒加载指令
const lazyLoad = {
  mounted(el, binding) {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          const img = el
          img.src = binding.value
          img.classList.add('fade-in')
          observer.unobserve(el)
        }
      })
    })
    
    observer.observe(el)
  }
}

// 复制指令
const copy = {
  mounted(el, binding) {
    el.addEventListener('click', () => {
      const text = binding.value
      navigator.clipboard.writeText(text).then(() => {
        ElMessage.success('复制成功')
      }).catch(() => {
        ElMessage.error('复制失败')
      })
    })
  }
}

// 注册全局指令
const app = createApp(App)
app.directive('permission', permission)
app.directive('lazy', lazyLoad)
app.directive('copy', copy)</code></pre>
      </section>

      <section class="chapter">
        <h2>性能优化深度实践</h2>

        <h3>组件级优化</h3>
        <p>合理的组件设计和渲染优化可以显著提升应用性能。</p>

        <pre><code>// 1. 函数式组件
const FunctionalButton = (props, { slots, emit }) => {
  return h('button', {
    class: ['btn', `btn-${props.type}`],
    onClick: () => emit('click')
  }, slots.default?.())
}

// 2. 异步组件 + Suspense
const AsyncModal = defineAsyncComponent({
  loader: () => import('./Modal.vue'),
  loadingComponent: LoadingSpinner,
  errorComponent: ErrorDisplay,
  delay: 200,
  timeout: 3000
})

// 3. KeepAlive 智能缓存
&lt;router-view v-slot="{ Component }"&gt;
  &lt;keep-alive 
    :include="['Home', 'UserProfile']"
    :max="10"
  &gt;
    &lt;component :is="Component" /&gt;
  &lt;/keep-alive&gt;
&lt;/router-view&gt;

// 4. 虚拟滚动优化
const VirtualList = defineComponent({
  props: {
    items: Array,
    itemSize: Number,
    buffer: { type: Number, default: 5 }
  },
  setup(props) {
    const containerRef = ref()
    const scrollTop = ref(0)
    const visibleCount = ref(0)
    
    const visibleItems = computed(() => {
      const start = Math.max(0, Math.floor(scrollTop.value / props.itemSize) - props.buffer)
      const end = start + visibleCount.value + props.buffer * 2
      return props.items.slice(start, end).map((item, index) => ({
        ...item,
        $index: start + index,
        $offset: (start + index) * props.itemSize
      }))
    })
    
    const containerStyle = computed(() => ({
      height: `${props.items.length * props.itemSize}px`
    }))
    
    const onScroll = () => {
      scrollTop.value = containerRef.value.scrollTop
    }
    
    onMounted(() => {
      visibleCount.value = Math.ceil(containerRef.value.clientHeight / props.itemSize)
    })
    
    return () => h('div', {
      ref: containerRef,
      class: 'virtual-container',
      onScroll
    }, [
      h('div', { class: 'virtual-wrapper', style: containerStyle.value },
        visibleItems.value.map(item => 
          h('div', {
            class: 'virtual-item',
            style: { transform: `translateY(${item.$offset}px)` }
          }, item.content)
        )
      )
    ])
  }
})</code></pre>

        <h3>应用级优化策略</h3>
        <p>从构建工具到运行时，全方位的性能优化策略。</p>

        <pre><code>// vite.config.js 构建优化
export default defineConfig({
  build: {
    // 代码分割
    rollupOptions: {
      output: {
        manualChunks: {
          'vue-vendor': ['vue', 'vue-router', 'pinia'],
          'element-ui': ['element-plus'],
          'utils': ['lodash-es', 'axios', 'dayjs']
        },
        chunkFileNames: 'assets/js/[name]-[hash].js',
        entryFileNames: 'assets/js/[name]-[hash].js',
        assetFileNames: 'assets/[ext]/[name]-[hash].[ext]'
      }
    },
    // 压缩优化
    minify: 'terser',
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true
      }
    }
  },
  // 依赖优化
  optimizeDeps: {
    include: ['vue', 'vue-router', 'pinia']
  }
})

// 路由懒加载优化
const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import(/* webpackChunkName: "home" */ '@/views/Home.vue')
  },
  {
    path: '/about',
    name: 'About', 
    component: () => import(
      /* webpackChunkName: "about" */
      /* webpackPrefetch: true */
      '@/views/About.vue'
    )
  }
]</code></pre>
      </section>

      <section class="chapter">
        <h2>测试策略与质量保证</h2>

        <h3>单元测试最佳实践</h3>
        <p>完善的测试覆盖是高质量代码的保证。</p>

        <pre><code>// 组件单元测试
import { mount } from '@vue/test-utils'
import { describe, it, expect, vi } from 'vitest'
import UserForm from './UserForm.vue'

describe('UserForm', () => {
  it('提交表单时触发 submit 事件', async () => {
    const wrapper = mount(UserForm)
    
    // 设置表单数据
    await wrapper.find('[data-test="name"]').setValue('张三')
    await wrapper.find('[data-test="email"]').setValue('zhangsan@example.com')
    
    // 提交表单
    await wrapper.find('form').trigger('submit.prevent')
    
    // 验证事件触发
    expect(wrapper.emitted('submit')[0]).toEqual([{
      name: '张三',
      email: 'zhangsan@example.com'
    }])
  })
  
  it('表单验证失败时显示错误信息', async () => {
    const wrapper = mount(UserForm)
    
    // 提交空表单
    await wrapper.find('form').trigger('submit.prevent')
    
    // 验证错误信息
    expect(wrapper.find('[data-test="name-error"]').exists()).toBe(true)
    expect(wrapper.find('[data-test="email-error"]').exists()).toBe(true)
  })
})

// Store 测试
import { setActivePinia, createPinia } from 'pinia'
import { useUserStore } from './userStore'

describe('User Store', () => {
  beforeEach(() => {
    setActivePinia(createPinia())
  })
  
  it('登录成功更新用户状态', async () => {
    const userStore = useUserStore()
    
    // Mock API 调用
    vi.spyOn(api, 'login').mockResolvedValue({
      user: { id: 1, name: '测试用户' },
      token: 'mock-token'
    })
    
    await userStore.login({ username: 'test', password: '123456' })
    
    expect(userStore.isLoggedIn).toBe(true)
    expect(userStore.user.name).toBe('测试用户')
  })
})</code></pre>

        <h3>E2E 测试完整流程</h3>
        <pre><code>// e2e/user-flow.spec.js
describe('用户完整流程', () => {
  it('应该能够完成注册、登录、下单流程', () => {
    // 访问首页
    cy.visit('/')
    
    // 注册新用户
    cy.get('[data-test="register-btn"]').click()
    cy.get('[data-test="username"]').type('newuser')
    cy.get('[data-test="email"]').type('newuser@example.com')
    cy.get('[data-test="password"]').type('password123')
    cy.get('[data-test="submit-register"]').click()
    
    // 验证注册成功
    cy.url().should('include', '/login')
    cy.contains('注册成功')
    
    // 登录
    cy.get('[data-test="email"]').type('newuser@example.com')
    cy.get('[data-test="password"]').type('password123')
    cy.get('[data-test="submit-login"]').click()
    
    // 验证登录成功
    cy.url().should('include', '/dashboard')
    cy.contains('欢迎，newuser')
    
    // 浏览商品并下单
    cy.get('[data-test="product-list"]').first().click()
    cy.get('[data-test="add-to-cart"]').click()
    cy.get('[data-test="cart-icon"]').click()
    cy.get('[data-test="checkout-btn"]').click()
    
    // 完成订单
    cy.get('[data-test="confirm-order"]').click()
    cy.contains('订单创建成功')
  })
})</code></pre>
      </section>

      <section class="conclusion">
        <h2>结语：Vue.js 的未来展望</h2>
        <p>
          Vue.js
          作为现代前端框架的杰出代表，不仅在技术上不断创新，更在开发者体验和社区生态建设上树立了标杆。随着
          Vue 3 的日益成熟和周边工具的不断完善，Vue
          生态系统正在进入一个全新的发展阶段。
        </p>
        <p>展望未来，Vue 将继续在以下几个方面发力：</p>
        <ul>
          <li>
            <strong>更好的 TypeScript 支持</strong
            >：提供更完善的类型推导和开发体验
          </li>
          <li>
            <strong>性能持续优化</strong>：编译时优化和运行时性能的进一步提升
          </li>
          <li>
            <strong>开发工具增强</strong>：Vue DevTools 和 Vite 的深度集成
          </li>
          <li><strong>多端开发支持</strong>：Vue 在移动端和桌面端的扩展</li>
          <li><strong>教育生态建设</strong>：降低学习门槛，扩大开发者社区</li>
        </ul>
        <p>
          作为 Vue
          开发者，我们应该持续学习新技术，深入理解框架原理，积极参与社区建设。只有这样，我们才能在这个快速变化的技术浪潮中保持竞争力，创造出更优秀的
          Web 应用。
        </p>
        <p class="final-thought">
          "技术之路，学无止境。Vue.js
          不仅是一个工具，更是一种思维方式，一种对优雅代码和卓越用户体验的执着追求。"
        </p>
      </section>
    </div>
  </div>
</template>

<script>
export default {
  name: "VueArticle",
};
</script>

<style scoped>
.vue-article {
  max-width: 1200px;
  margin: 0 auto;
  padding: 40px 20px;
  background: #fff;
  line-height: 1.8;
  color: #333;
}

.article-header {
  text-align: center;
  margin-bottom: 50px;
  padding-bottom: 30px;
  border-bottom: 3px solid #42b883;
}

.article-header h1 {
  font-size: 2.8em;
  color: #2c3e50;
  margin-bottom: 20px;
  font-weight: 700;
}

.meta-info {
  display: flex;
  justify-content: center;
  gap: 30px;
  color: #7f8c8d;
  font-size: 0.95em;
}

.article-content {
  max-width: 900px;
  margin: 0 auto;
}

.chapter {
  margin-bottom: 60px;
}

.chapter h2 {
  font-size: 2em;
  color: #34495e;
  margin-bottom: 25px;
  padding-bottom: 15px;
  border-bottom: 2px solid #42b883;
}

.chapter h3 {
  font-size: 1.5em;
  color: #2c3e50;
  margin: 30px 0 15px;
}

p {
  margin-bottom: 20px;
  text-align: justify;
  font-size: 1.05em;
}

pre {
  background: #f8f9fa;
  border: 1px solid #e9ecef;
  border-radius: 8px;
  padding: 25px;
  margin: 20px 0;
  overflow-x: auto;
  font-family: "Fira Code", "Courier New", monospace;
  font-size: 0.9em;
  line-height: 1.5;
}

code {
  font-family: "Fira Code", "Courier New", monospace;
}

ul {
  margin: 20px 0;
  padding-left: 30px;
}

li {
  margin-bottom: 10px;
  font-size: 1.05em;
}

.conclusion {
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
  padding: 40px;
  border-radius: 15px;
  margin-top: 50px;
  border-left: 5px solid #42b883;
}

.conclusion h2 {
  color: #27ae60;
  border-bottom-color: #27ae60;
}

.final-thought {
  font-style: italic;
  text-align: center;
  font-size: 1.1em;
  color: #7f8c8d;
  margin-top: 30px;
  padding: 20px;
  background: white;
  border-radius: 8px;
  border-left: 4px solid #3498db;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .vue-article {
    padding: 20px 15px;
  }

  .article-header h1 {
    font-size: 2em;
  }

  .meta-info {
    flex-direction: column;
    gap: 10px;
  }

  .chapter h2 {
    font-size: 1.6em;
  }

  .chapter h3 {
    font-size: 1.3em;
  }

  pre {
    padding: 15px;
    font-size: 0.8em;
  }

  .conclusion {
    padding: 25px;
  }
}

/* 代码高亮增强 */
pre code {
  display: block;
}

/* 滚动条样式 */
.vue-article::-webkit-scrollbar {
  width: 12px;
}

.vue-article::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 6px;
}

.vue-article::-webkit-scrollbar-thumb {
  background: linear-gradient(135deg, #42b883, #35495e);
  border-radius: 6px;
  border: 2px solid #f1f1f1;
}

.vue-article::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(135deg, #3498db, #2c3e50);
}
</style>
